home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / Source / Halma 1.1.source Folder / Halma ƒ / Shell ƒ / prefs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-25  |  12.7 KB  |  455 lines  |  [TEXT/KAHL]

  1. /**********************************************************************\
  2.  
  3. File:        prefs.c
  4.  
  5. Purpose:    This module handles creating/opening/closing/updating
  6.             the preference file, and copying the preference file
  7.             data into application globals (and back).
  8.  
  9. This program is free software; you can redistribute it and/or modify
  10. it under the terms of the GNU General Public License as published by
  11. the Free Software Foundation; either version 2 of the License, or
  12. (at your option) any later version.
  13.  
  14. This program is distributed in the hope that it will be useful,
  15. but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. GNU General Public License for more details.
  18.  
  19. You should have received a copy of the GNU General Public License
  20. along with this program in a file named "GNU General Public License".
  21. If not, write to the Free Software Foundation, 675 Mass Ave,
  22. Cambridge, MA 02139, USA.
  23.  
  24. \**********************************************************************/
  25.  
  26. #include "program globals.h"
  27. #include "prefs.h"
  28. #include "help.h"
  29. #include "dialogs.h"
  30. #include "environment.h"
  31. #include "util.h"
  32. #include "sounds.h"
  33. #include "Folders.h"
  34.  
  35. #define        PREFS_FILE_NAME            "\pHalma prefs"
  36. #define        PREFS_TYPE                'PREF'
  37. // CREATOR is #defined in "program globals.h"
  38. #define        PREFS_HEADER_VERSION    2
  39.  
  40. Boolean            gCanSavePrefs;
  41. Str255            gMyName;
  42. Str255            gMyOrg;
  43.  
  44. typedef struct
  45. {
  46.     char            regname[40];
  47.     char            regorg[40];
  48.     unsigned char    sound;
  49.     unsigned char    doesntmutate;
  50.     unsigned char    snowcolor;
  51.     unsigned char    snowspeed;
  52.     short            numrows;
  53.     short            numcolumns;
  54.     short            maintopic;
  55.     short            subtopic;
  56.     long            fileID;
  57. } PrefStruct;
  58.  
  59. /* internal globals for use in prefs.c only */
  60. static long            gFileID;
  61. static Boolean        gCanSavePrefs;
  62. static PrefStruct    thePrefs;
  63. static long            gPrefsFilePos;
  64.  
  65. /*-----------------------------------------------------------------------------------*/
  66. /* internal stuff for prefs.c                                                        */
  67.  
  68. enum PrefErrorTypes OpenPrefsFile(short *prefsFileID);
  69. enum PrefErrorTypes SetupNewPrefsFile(short prefsFileID);
  70. void ClosePrefsFile(short prefsFileID);
  71. enum PrefErrorTypes GetNextPrefs(short prefsFileID);
  72. enum PrefErrorTypes SavePrefs(short prefsFileID);
  73. enum PrefErrorTypes CheckVersion(short prefsFileID);
  74. enum PrefErrorTypes GetFileID(void);
  75. enum PrefErrorTypes CheckFileID(void);
  76. enum PrefErrorTypes Virgin(short prefsFileID);
  77. void DefaultPrefs(void);
  78. void CopyGlobalsToPrefs(void);
  79. void CopyPrefsToGlobals(void);
  80. void GetRegistration(void);
  81.  
  82. void SaveThePrefs(void)
  83. /* standard procedure callable from anywhere to save prefs to disk (if possible) */
  84. {
  85.     short            prefsFileID;
  86.     
  87.     if (gCanSavePrefs)        /* if we had no errors in PreferencesInit() */
  88.     {
  89.         OpenPrefsFile(&prefsFileID);    /* open the prefs file */
  90.         CopyGlobalsToPrefs();            /* copy global variables to prefs struct */
  91.         SavePrefs(prefsFileID);            /* save prefs to disk */
  92.         ClosePrefsFile(prefsFileID);    /* close prefs file */
  93.     }
  94. }
  95.  
  96. enum PrefErrorTypes PreferencesInit(void)
  97. {
  98.     short            prefsFileID;
  99.     enum PrefErrorTypes        err;
  100.     
  101.     gCanSavePrefs=FALSE;    /* assume the worst and maybe you'll be pleasantly surprised */
  102.     err=GetFileID();        /* get application file ID */
  103.     if (err!=prefs_allsWell)    /* screwed up already?!? */
  104.         return err;
  105.     
  106.     err=OpenPrefsFile(&prefsFileID);    /* open prefs file (or create new one) */
  107.     if (err!=prefs_allsWell)
  108.     {
  109.         if ((err==prefs_diskReadErr) || (err==prefs_diskWriteErr) || (err==prefs_virginErr))
  110.             ClosePrefsFile(prefsFileID);    /* close & abort if error or if new prefs */
  111.         return err;
  112.     }
  113.     
  114.     err=CheckVersion(prefsFileID);        /* check prefs version */
  115.     if (err!=prefs_allsWell)
  116.     {
  117.         ClosePrefsFile(prefsFileID);
  118.         return err;
  119.     }
  120.     
  121.     GetFPos(prefsFileID, &gPrefsFilePos);
  122.     gPrefsFilePos-=sizeof(thePrefs);
  123.     do
  124.     {
  125.         gPrefsFilePos+=sizeof(thePrefs);
  126.         err=GetNextPrefs(prefsFileID);        /* get prefs struct from file */
  127.         if (err==prefs_noMorePrefsErr)        /* or not */
  128.             return (Virgin(prefsFileID));    /* can't find our file ID, it's our first time */
  129.         
  130.         if (err!=prefs_allsWell)            /* any other error, just abort */
  131.         {
  132.             ClosePrefsFile(prefsFileID);
  133.             return err;
  134.         }
  135.         
  136.         err=CheckFileID();                    /* check file ID of current prefs struct */
  137.     }
  138.     while (err==prefs_IDNotMatchErr);
  139.     
  140.     CopyPrefsToGlobals();                    /* copy prefs struct to program globals */
  141.     ClosePrefsFile(prefsFileID);            /* close prefs file */
  142.     
  143.     return prefs_allsWell;                    /* piece o' cake */
  144. }
  145.  
  146. void PrefsError(enum PrefErrorTypes err)
  147. {
  148.     Str255            tempStr;
  149.     
  150.     switch (err)
  151.     {
  152.         case prefs_diskReadErr:
  153.         case prefs_diskWriteErr:
  154.         case prefs_cantCreatePrefsErr:
  155.         case prefs_cantOpenPrefsErr:
  156.         case prefs_versionNotSupportedErr:
  157.             DefaultPrefs();                    /* use default prefs if error */
  158.             gCanSavePrefs=FALSE;            /* don't bother trying to save prefs later */
  159.             GetIndString(tempStr, 128, err);    /* get error string from .rsrc file */
  160.             ParamText(tempStr, "\p", "\p", "\p");
  161.             PositionDialog('ALRT', largeAlert);
  162.             StopAlert(largeAlert, 0L);        /* display error alert */
  163.             break;
  164.         default:
  165.             gCanSavePrefs=TRUE;                /* can save prefs to disk later if needed */
  166.             break;
  167.     }
  168. }
  169.  
  170. enum PrefErrorTypes OpenPrefsFile(short *prefsFileID)
  171. {
  172.     short            thisFile;
  173.     OSErr            isHuman;
  174.     short            vRefNum;
  175.     long            dirID;
  176.     FSSpec            prefsFile;
  177.     FInfo            prefsInfo;
  178.     Boolean            newPrefs;
  179.     unsigned char    *name=PREFS_FILE_NAME;
  180.     
  181.     newPrefs=FALSE;
  182.     /* find vRefNum and dirID of preferences folder, creating it if necessary */
  183.     isHuman=FindFolder(kOnSystemDisk, 'pref', kCreateFolder, &vRefNum, &dirID);
  184.     
  185.     if (isHuman!=noErr)        /* screwed up already?!? */
  186.         return prefs_cantOpenPrefsErr;
  187.     if (gHasFSSpecs)
  188.     {
  189.         isHuman=FSMakeFSSpec(vRefNum, dirID, name, &prefsFile);    /* make FSSpec out of it */
  190.         if (isHuman!=noErr)
  191.         {
  192.             if (isHuman==fnfErr)    /* FSSpec is valid, but prefs file does not exist */
  193.             {
  194.                 isHuman=FSpCreate(&prefsFile, CREATOR, PREFS_TYPE, 0);    /* so create it */
  195.                 if (isHuman!=noErr)                                        /* or not */
  196.                     return prefs_cantCreatePrefsErr;
  197.                 newPrefs=TRUE;        /* signal that prefs file is new */
  198.             }
  199.             else return prefs_cantOpenPrefsErr;
  200.         }
  201.         isHuman=FSpOpenDF(&prefsFile, fsRdWrPerm, &thisFile);    /* open prefs file */
  202.         *prefsFileID=thisFile;        /* store file reference number */
  203.         if (isHuman!=noErr)
  204.             return prefs_cantOpenPrefsErr;
  205.     }
  206.     else
  207.     {
  208.         /* try to open prefs file */
  209.         isHuman=HOpen(vRefNum, dirID, name, fsRdWrPerm, &thisFile);
  210.         *prefsFileID=thisFile;
  211.         if (isHuman!=noErr)
  212.         {
  213.             if (isHuman==fnfErr)    /* prefs file does not exist */
  214.             {
  215.                 /* ...so create it */
  216.                 if (HCreate(vRefNum, dirID, name, CREATOR, PREFS_TYPE)!=noErr)
  217.                     return prefs_cantCreatePrefsErr;
  218.                 prefsInfo.fdType=PREFS_TYPE;
  219.                 prefsInfo.fdCreator=CREATOR;
  220.                 prefsInfo.fdFlags=0;
  221.                 prefsInfo.fdLocation.h=prefsInfo.fdLocation.v=0;
  222.                 prefsInfo.fdFldr=0;
  223.                 
  224.                 /* set file info of newly created prefs file */
  225.                 if (HSetFInfo(vRefNum, dirID, name, &prefsInfo)!=noErr)
  226.                     return prefs_cantCreatePrefsErr;
  227.                 
  228.                 /* NOW open the prefs file */
  229.                 isHuman=HOpen(vRefNum, dirID, name, fsRdWrPerm, &thisFile);
  230.                 *prefsFileID=thisFile;        /* store file reference number */
  231.                 if (isHuman!=noErr)
  232.                     return prefs_cantOpenPrefsErr;
  233.                 newPrefs=TRUE;                /* signal that prefs file is new */
  234.             }
  235.             else return prefs_cantOpenPrefsErr;
  236.         }
  237.     }
  238.     if (newPrefs)
  239.         return SetupNewPrefsFile(*prefsFileID);        /* needs initial setup if new */
  240.     
  241.     return prefs_allsWell;
  242. }
  243.  
  244. enum PrefErrorTypes SetupNewPrefsFile(short prefsFileID)
  245. /* this writes the prefs version number to the newly created prefs file, so we can
  246.    tell if the prefs file was created by a later version of the program and is
  247.    therefore in a format that we don't support -- forward compatability!  what
  248.    a concept! */
  249. {
  250.     long            count;
  251.     short            temp;
  252.     
  253.     gPrefsFilePos=2L;
  254.     if (SetEOF(prefsFileID, 2L)!=noErr)    /* set length of prefs file to 2 */
  255.         return prefs_diskWriteErr;
  256.     
  257.     SetFPos(prefsFileID, 1, 0L);
  258.     temp=PREFS_HEADER_VERSION;            /* get the prefs version (hardcoded) */
  259.     count=2L;
  260.     if (FSWrite(prefsFileID, &count, &temp)!=noErr)        /* write prefs version */
  261.         return prefs_diskWriteErr;        
  262.     
  263.     return Virgin(prefsFileID);            /* be gentle; it's our first time */
  264. }
  265.  
  266. void ClosePrefsFile(short prefsFileID)
  267. {
  268.     FSClose(prefsFileID);                /* close file on disk */
  269.     FlushVol(0L, kOnSystemDisk);        /* flush volume to write out new info */
  270. }
  271.  
  272. enum PrefErrorTypes GetNextPrefs(short prefsFileID)
  273. {
  274.     OSErr        isHuman;
  275.     long        count;
  276.     
  277.     count=sizeof(thePrefs);
  278.     isHuman=FSRead(prefsFileID, &count, &thePrefs);        /* get next prefs struct */
  279.     if (isHuman==eofErr)    /* no more left */
  280.         return prefs_noMorePrefsErr;
  281.     if (isHuman!=noErr)        /* some other error */
  282.         return prefs_diskReadErr;
  283.     
  284.     return prefs_allsWell;
  285. }
  286.  
  287. enum PrefErrorTypes SavePrefs(short prefsFileID)
  288. {
  289.     long        oldEOF;
  290.     long        count;
  291.     
  292.     GetEOF(prefsFileID, &oldEOF);
  293.     if (gPrefsFilePos>=oldEOF)        /* add new prefs struct onto end of prefs file */
  294.     {
  295.         if (SetEOF(prefsFileID, oldEOF+sizeof(thePrefs))!=noErr)
  296.             return prefs_diskWriteErr;
  297.     }
  298.     
  299.     SetFPos(prefsFileID, 1, gPrefsFilePos);        /* set position inside prefs file */
  300.     count=sizeof(thePrefs);
  301.     /* write prefs struct and return appropriate error code */
  302.     return (FSWrite(prefsFileID, &count, &thePrefs)!=noErr) ?
  303.         prefs_diskWriteErr : prefs_allsWell;
  304. }
  305.  
  306. enum PrefErrorTypes CheckVersion(short prefsFileID)
  307. {
  308.     OSErr        isHuman;
  309.     long        count;
  310.     short            temp;
  311.     
  312.     count=2L;
  313.     isHuman=FSRead(prefsFileID, &count, &temp);        /* get prefs version */
  314.     if (isHuman!=noErr)
  315.         return prefs_diskReadErr;
  316.     if (temp>PREFS_HEADER_VERSION)                    /* too new */
  317.         return prefs_versionNotSupportedErr;
  318.     if (temp<PREFS_HEADER_VERSION)                    /* old; overwrite */
  319.         return SetupNewPrefsFile(prefsFileID);
  320.     
  321.     return prefs_allsWell;
  322. }
  323.  
  324. enum PrefErrorTypes GetFileID(void)
  325. {
  326.     ParamBlockRec    pb;
  327.     
  328.     pb.fileParam.ioCompletion=0L;
  329.     pb.fileParam.ioNamePtr=CurApName;
  330.     pb.fileParam.ioVRefNum=0;
  331.     pb.fileParam.ioFVersNum=0;
  332.     pb.fileParam.ioFDirIndex=0;
  333.     if (PBGetFInfo(&pb, FALSE)!=noErr)
  334.         return prefs_diskReadErr;
  335.     
  336.     gFileID=pb.fileParam.ioFlNum;
  337. }
  338.  
  339. enum PrefErrorTypes CheckFileID(void)
  340. {
  341.     /* compare file ID in current prefs struct to application's file ID */
  342.     return (thePrefs.fileID==gFileID) ? prefs_allsWell : prefs_IDNotMatchErr;
  343. }
  344.  
  345. enum PrefErrorTypes Virgin(short prefsFileID)
  346. {
  347.     short            err;
  348.     
  349.     DefaultPrefs();
  350.     CopyGlobalsToPrefs();
  351.     err=SavePrefs(prefsFileID);
  352.     if (err!=prefs_allsWell)
  353.         return err;
  354.     DoSound(sound_virgin, TRUE);
  355.     GetRegistration();
  356.     CopyGlobalsToPrefs();
  357.     err=SavePrefs(prefsFileID);
  358.     
  359.     return (err==prefs_allsWell) ? prefs_virginErr : err;
  360. }
  361.  
  362. void DefaultPrefs(void)
  363. {
  364.     unsigned char        *bob="\pBob";
  365.     
  366.     Mymemcpy((Ptr)gMyName, (Ptr)bob, bob[0]+1);
  367.     gMyOrg[0]=0x00;
  368.     gSnowColor=0x07;    /* white */
  369.     gSnowSpeed=0x03;    /* fast */
  370.     gSnowMutates=0xff;    /* true */
  371.     gSoundToggle=0xFF;
  372.     gNumRows=4;
  373.     gNumColumns=6;
  374.     gMainTopicShowing=gSubTopicShowing=0;
  375. }
  376.  
  377. void CopyGlobalsToPrefs(void)
  378. {
  379.     Mymemset((Ptr)(&thePrefs), 0, sizeof(thePrefs));
  380.     if (gMyName[0]>0x27)
  381.         gMyName[0]=0x27;
  382.     if (gMyOrg[0]>0x27)
  383.         gMyOrg[0]=0x27;
  384.     Mymemcpy((Ptr)thePrefs.regname, (Ptr)gMyName, gMyName[0]+1);
  385.     Mymemcpy((Ptr)thePrefs.regorg, (Ptr)gMyOrg, gMyOrg[0]+1);
  386.     thePrefs.maintopic=gMainTopicShowing;
  387.     thePrefs.subtopic=gSubTopicShowing;
  388.     thePrefs.fileID=gFileID;
  389.     
  390.     thePrefs.sound=gSoundToggle;
  391.     thePrefs.doesntmutate=gSnowMutates^0xff;
  392.     thePrefs.snowcolor=gSnowColor;
  393.     thePrefs.snowspeed=gSnowSpeed;
  394.     thePrefs.numrows=gNumRows;
  395.     thePrefs.numcolumns=gNumColumns;
  396. }
  397.  
  398. void CopyPrefsToGlobals(void)
  399. {
  400.     Mymemcpy((Ptr)gMyName, (Ptr)thePrefs.regname, thePrefs.regname[0]+1);
  401.     Mymemcpy((Ptr)gMyOrg, (Ptr)thePrefs.regorg, thePrefs.regorg[0]+1);
  402.     gMainTopicShowing=thePrefs.maintopic;
  403.     gSubTopicShowing=thePrefs.subtopic;
  404.     
  405.     gSnowMutates=thePrefs.doesntmutate^0xff;
  406.     gSnowColor=thePrefs.snowcolor;
  407.     gSnowSpeed=thePrefs.snowspeed;
  408.     gSoundToggle=thePrefs.sound;
  409.     gNumRows=thePrefs.numrows;
  410.     gNumColumns=thePrefs.numcolumns;
  411. }
  412.  
  413. void GetRegistration(void)
  414. {
  415.     DialogPtr        theDlog;
  416.     short            itemSelected = 0;
  417.     short            newleft;
  418.     short            newtop;
  419.     short            itemType;
  420.     Handle            item;
  421.     Rect            box;
  422.     
  423.     theDlog = GetNewDialog(personalDialog, 0L, (WindowPtr)-1L);
  424.     newleft = screenBits.bounds.left + (((screenBits.bounds.right -
  425.                 screenBits.bounds.left) - (theDlog->portRect.right -
  426.                 theDlog->portRect.left)) / 2);
  427.     newtop = screenBits.bounds.top + (((screenBits.bounds.bottom -
  428.                 screenBits.bounds.top) - (theDlog->portRect.bottom -
  429.                 theDlog->portRect.top)) / 2);
  430.     if(newtop < 15)
  431.         newtop = 15;
  432.     GetDItem(theDlog, 1, &itemType, &item, &box);
  433.     InsetRect(&box, -4, -4);
  434.     SetDItem(theDlog, 8, userItem, (ProcPtr)OutlineDefaultButton, &box);
  435.     ParamText(APPLICATION_NAME, "\p", "\p", "\p");
  436.     
  437.     MoveWindow(theDlog, newleft, newtop, TRUE);
  438.     ShowWindow(theDlog);
  439.     while(itemSelected != 1)
  440.     {
  441.         ModalDialog(0L, &itemSelected);
  442.     }
  443.     GetDItem(theDlog,4,&itemType,&item,&box);
  444.     GetIText(item,gMyName);
  445.     
  446.     GetDItem(theDlog,5,&itemType,&item,&box);
  447.     GetIText(item,gMyOrg);
  448.  
  449.     if (gMyName[0]==0x00)
  450.         DefaultPrefs();
  451.  
  452.     HideWindow(theDlog);
  453.     DisposeDialog(theDlog);
  454. }
  455.